package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"
	"path/filepath"
	"text/template"
	"time"
)

type Page struct {
	Title string
	Count int
	Files []string
	Body  []byte
}

var (
	lookfor   = "filename"
	files     map[string][]string
	filelist  []string
	filecount int
)

var all *bool = flag.Bool("all", false, "include hidden directories (.*)")

func visit(path string, f os.FileInfo, err error) error {
	if !*all && f.Mode() & os.ModeDir != 0 && f.Name()[0] == '.' {
		return filepath.SkipDir
	}
	file := filepath.Base(path)
	o := files[file]
	o = append(o, path)
	files[file] = o
	filecount++
	if filecount%10000 == 0 {
		fmt.Printf("%d, ", filecount)
	}
	//fmt.Printf("path: %s file: %s\n", path, file)
	return nil
}

func walk(dirs []string) {
	files = make(map[string][]string, 1024)
	start := time.Now()
	filecount = 0

	for _, dir := range dirs {
		fmt.Println("dir", dir)
		root, err := filepath.Abs(dir)
		if err != nil {
			fmt.Println("couldn't resolve directory", dir, err)
		}
		err = filepath.Walk(root, visit)
		if err != nil {
			fmt.Println("error walking", root, err)
		}
	}
	end := time.Now()
	duration := float64(end.Sub(start)) / 1e9
	fmt.Println()
	fmt.Printf("%v files in %v seconds %v/second\n",
		filecount, duration, float64(filecount)/(duration))

}

func loadPage(title string) (*Page, error) {
	x := []uint8(lookfor)
	return &Page{Title: title, Files: filelist, Count: filecount, Body: x}, nil
}

func editHandler(w http.ResponseWriter, r *http.Request, title string) {
	//fmt.Printf("editHanlder w %v r %v title %v\n", w, r, title)
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}
	renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
	lookfor = r.FormValue("file")
	http.Redirect(w, r, "/"+title, http.StatusFound)
}

var templates = make(map[string]*template.Template)

func init() {
	for _, tmpl := range []string{"edit"} {
		t := template.Must(template.ParseFiles(tmpl + ".html"))
		templates[tmpl] = t
	}
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	err := templates[tmpl].Execute(w, p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

const lenPath = len("/edit/")

func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {

	return func(w http.ResponseWriter, r *http.Request) {
		ok := false
		finfo, ok := files[lookfor]
		title := lookfor
		if !ok {
			title = title + " not found"
		}
		filelist = []string{}
		for _, i := range finfo {
			filelist = append(filelist, i)
		}
		//fmt.Println("Looking for", lookfor, "found", finfo)
		fn(w, r, title)
	}
}

func main() {
	flag.Parse()
	root := flag.Args()
	//	http.HandleFunc("/view/", makeHandler(viewHandler))
	http.HandleFunc("/", makeHandler(editHandler))
	http.HandleFunc("/save/", makeHandler(saveHandler))
	walk(root)
	http.ListenAndServe(":8086", nil)
}
